package cn.stu.framework.service.impl;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import cn.stu.common.utils.*;
import cn.stu.framework.dto.UserDisableDto;
import cn.stu.framework.dto.UsersDetailDto;
import cn.stu.framework.entity.Users;
import cn.stu.framework.entity.UsersDetail;
import cn.stu.framework.mapper.RoleMapper;
import cn.stu.framework.mapper.UsersDetailMapper;
import cn.stu.framework.mapper.UsersMapper;
import cn.stu.framework.service.UsersDetailService;
import cn.stu.framework.service.UsersService;
import cn.stu.framework.vo.UsersDetailVo;
import cn.stu.framework.vo.UsersVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.web.multipart.MultipartFile;

import static cn.stu.common.utils.SystemConstants.IMAGE_USERS_DEFAULT_DIR;
import static cn.stu.common.utils.SystemConstants.LOGIN_USER_KEY;


/**
 * 实施用户详细信息服务
 *
 * @author 郑志豪
 * @date 2023/10/31
 */
@Service
@Log4j2
@AllArgsConstructor
public class UsersDetailServiceImpl extends ServiceImpl<UsersDetailMapper, UsersDetail> implements UsersDetailService {
    private UsersMapper usersMapper;

    private UsersService usersService;

    private RoleMapper roleMapper;

    private MinioTool minioTool;

    private StringRedisTemplate stringRedisTemplate;


    @Override
    @Cacheable(value = "userDetail", key = "'userId:'+#userId", sync = true)
    public R<UsersVo> userInfo(Long userId) {
        UsersVo info = usersMapper.userMsg(userId);
        return R.ok(info, "获取成功!");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "UsersDetailList", allEntries = true, beforeInvocation = true)
    public ApiData userAdd(UsersDetailVo urs) {
        if (usersService.lambdaQuery().eq(Users::getAcc, urs.getAcc()).exists()) {
            return ApiData.getFalse("登录名已存在，请更换其他登录名！");
        }
        UsersDetail add = BeanUtils.beanCopier(urs, new UsersDetail());
        add.setHireTime(MyTools.turnDate(urs.getHireTimes()));
        add.setUserImage(IMAGE_USERS_DEFAULT_DIR);
        //md5加密
        String password = DigestUtils.md5DigestAsHex("123456".getBytes());
        //用户表数据
        Users add1 = BeanUtils.beanCopier(urs, new Users());
        add1.setPwd(password);
        usersMapper.insert(add1);
        add.setUserId(add1.getUserId());
        baseMapper.insert(add);
        return ApiData.getTrue("添加成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict = {
            @CacheEvict(value = "UsersDetailList", allEntries = true, beforeInvocation = true),
            @CacheEvict(value = "userDetail", key = "'userId:'+#userId", beforeInvocation = true)
    })
    public ApiData userDel(Long userId, String pwd) {
        Long updateId = UserHolder.getUser().getUserId();
        if (userId == null) {
            return ApiData.getFalse("id为空!");
        }
        if (StrUtil.isBlank(pwd)) {
            return ApiData.getFalse("密码错误!");
        }
        if (userId == 1) {
            return ApiData.getFalse("超管账户不允许操作!");
        }
        Users user = usersMapper.selectById(userId);
        if (user == null) {
            return ApiData.getFalse("用户不存在!");
        }
        Users updateUser = usersMapper.selectById(updateId);
        if (!updateUser.getPwd().equals(pwd)) {
            return ApiData.getFalse("密码错误!");
        }
        //用户表逻辑删除
        usersMapper.deleteById(userId);
        //用户详情表逻辑删除
        lambdaUpdate().eq(UsersDetail::getUserId, userId).remove();
        String tokenKey = LOGIN_USER_KEY + userId;
        stringRedisTemplate.delete(tokenKey);
        return ApiData.getTrue("删除成功!");
    }

    @Override
    public ApiData userReset(Long userId) {
        if (userId == null) {
            return ApiData.getFalse("id为空!");
        }
        Users u = usersMapper.selectById(userId);
        if (u == null) {
            return ApiData.getFalse("id不存在!");
        }
        String resetPwd = MyTools.generatePassword(8);
        String password = DigestUtils.md5DigestAsHex(resetPwd.getBytes());
        usersService.lambdaUpdate().set(Users::getPwd, password)
                .eq(Users::getUserId, userId)
                .update();
        return ApiData.getTrue("重置成功，密码已经重置为" + resetPwd);
    }

    /**
     * 用户更新
     *
     * @param urs URS
     * @return {@link ApiData}
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict = {
            @CacheEvict(value = "UsersDetailList", allEntries = true, beforeInvocation = true),
            @CacheEvict(value = "userDetail", key = "'userId:'+#urs.userId", beforeInvocation = true)
    })
    public ApiData userUpdate(UsersDetailVo urs) {
        Users u = usersMapper.selectById(urs.getUserId());
        if (u == null) {
            return ApiData.getFalse("用户" + "不存在！");
        }
        if (!urs.getAcc().equals(u.getAcc())) {
            LambdaQueryWrapper<Users> query = new LambdaQueryWrapper<>();
            query.eq(Users::getAcc, urs.getAcc());
            if ((usersMapper.exists(query))) {
                return ApiData.getFalse("账号已存在，请更换！");
            }
        }
        if (urs.getRoleId() != null && roleMapper.selectById(urs.getRoleId()) == null) {
            return ApiData.getFalse("此角色" + "不存在！");
        }
        String fileUrl = null;
        UsersDetail oldDetail = baseMapper.selectById(UserHolder.getUser().getUserId());
        // 取出文件
        if (!StrUtil.isBlank(urs.getUserImage()) && !oldDetail.getUserImage().equals(urs.getUserImage())) {
            try {
                if (!StrUtil.isBlank(oldDetail.getUserImage())) {
                    String oldFilePath = extractFileName(oldDetail.getUserImage());
                    //删除旧头像
                    if (!minioTool.removeBucketObject(minioTool.avatarBucketName, UserHolder.getUser().getUserId() + "/" + oldFilePath)) {
                        System.out.println("删除异常");
                    }
                }
                String newFilePath = u.getUserId() + "/" + urs.getUserImage();
                //文件移动
                minioTool.bucketFileMove(minioTool.tempBucketName, urs.getUserImage(), minioTool.avatarBucketName, newFilePath);
                //获取头像地址
                String url = minioTool.getFileUrl(minioTool.avatarBucketName, newFilePath);
                fileUrl = url.substring(url.lastIndexOf(":9000") + 5);
            } catch (Exception e) {
                log.error(e.getMessage());
                return ApiData.getFalse("修改异常！");
            }
        }
        //详情表数据
        UsersDetail update = BeanUtils.beanCopier(urs, new UsersDetail());
        if (urs.getHireTimes() != null) {
            update.setHireTime(MyTools.turnDate(urs.getHireTimes()));
        }
        if (!StrUtil.isBlank(urs.getUserImage()) && !oldDetail.getUserImage().equals(urs.getUserImage())) {
            update.setUserImage(fileUrl);
        }
        //用户表数据
        Users updateUser = BeanUtils.beanCopier(urs, new Users());
        updateUser.setPwd(u.getPwd());
        if (urs.getRoleId() != null) {
            updateUser.setRoleId(urs.getRoleId());
        } else {
            updateUser.setRoleId(u.getRoleId());
        }
        usersMapper.updateById(updateUser);
        lambdaUpdate().eq(UsersDetail::getUserId, urs.getUserId()).update(update);
        return ApiData.getTrue("修改成功");
    }

    @Override
    @Cacheable(value = "UsersDetailList", sync = true)
    public ApiData selectContacts(UsersDetailDto usersDetailDto) {
        if (usersDetailDto.getLimit() == null || usersDetailDto.getPage() == null) {
            return ApiData.getFalse("获取失败");
        }
        Page<UsersDetailVo> page = new Page<>(usersDetailDto.getPage(), usersDetailDto.getLimit());
        baseMapper.getContacts(page, usersDetailDto.getDeptId(), usersDetailDto.getName(), usersDetailDto.getTel());
        return ApiData.getPageTrue("获取成功", page.getTotal(), page.getRecords());
    }

    /**
     * 用户禁用
     *
     * @param userDisableDto 用户禁用dto
     * @return {@link ApiData}
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict = {
            @CacheEvict(value = "UsersDetailList", allEntries = true, beforeInvocation = true),
            @CacheEvict(value = "userDetail", key = "'userId:'+#userDisableDto.userId", beforeInvocation = true)
    })
    public ApiData userDisabled(UserDisableDto userDisableDto) {
        if (userDisableDto.getUserId() == null) {
            return ApiData.getFalse("id为空!");
        }
        if (userDisableDto.getUserId() == 1) {
            return ApiData.getFalse("超管账户不允许操作!");
        }
        Long userId = userDisableDto.getUserId();
        UsersVo user = usersMapper.userMsg(userId);
        if (user == null) {
            return ApiData.getFalse("用户不存在!");
        }
        if (!user.getAcc().equals(userDisableDto.getAcc()) || !user.getName().equals(userDisableDto.getName())) {
            return ApiData.getFalse("用户不存在!");
        }
        Long updateId = UserHolder.getUser().getUserId();
        int disable = user.getIsDisable();
        if (disable == 0) {
            disable = 1;
        } else {
            disable = 0;
        }
        Users update = new Users();
        update.setUserId(userId);
        update.setIsDisable(disable);
        usersMapper.updateById(update);
        String tokenKey = LOGIN_USER_KEY + userId;
        stringRedisTemplate.delete(tokenKey);
        return ApiData.getTrue("账号" + user.getAcc() + (disable == 0 ? "启用" : "禁用") + "成功!");
    }

    @Override
    @Cacheable(value = "UserList", sync = true)
    public R selectUserList(UsersDetail usersDetail) {
        return R.ok(baseMapper.getUserList());
    }

    /**
     * 文件上传
     *
     * @param newImg 新img
     * @return {@link ApiData}
     */
    @Override
    public ApiData fileUpload(MultipartFile newImg) {
        if (newImg == null) {
            return ApiData.getFalse("无头像文件");
        }
        //获取UUID
        String id = UUID.randomUUID().toString(true);
        //获取文件名
        String originalFilename = newImg.getOriginalFilename();
        //重命名文件名
        String rename;
        if (originalFilename != null) {
            rename = id + originalFilename.substring(originalFilename.lastIndexOf("."));
        } else {
            return ApiData.getFalse("文件名后缀获取异常！");
        }
        Boolean upload = minioTool.upload(minioTool.tempBucketName, newImg, rename);
        if (!upload) {
            return ApiData.getFalse("上传失败");
        }
        return ApiData.getTrue("上传成功", rename);
    }

    private static String extractFileName(String input) {
        // 查找文件名的起始位置和结束位置
        int startIndex = input.lastIndexOf("/") + 1;
        int endIndex = input.indexOf(".") + 4;
        // 提取文件名部分
        return input.substring(startIndex, endIndex);
    }
}
